package com.wjbgn.bsolver.server.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.wjbgn.bsolver.server.api.UserClient;
import com.wjbgn.bsolver.server.convert.BugAnsweredRecordDoConvert;
import com.wjbgn.bsolver.server.dto.AchievementDTO;
import com.wjbgn.bsolver.server.dto.BugAnsweredRecordDTO;
import com.wjbgn.bsolver.server.dto.UserDTO;
import com.wjbgn.bsolver.server.entity.BugAnsweredRecordDO;
import com.wjbgn.bsolver.server.enums.SortEnum;
import com.wjbgn.bsolver.server.mapper.BugAnsweredRecordMapper;
import com.wjbgn.bsolver.server.service.IBugAnswerAcceptRejectService;
import com.wjbgn.bsolver.server.service.IBugAnsweredRecordService;
import com.wjbgn.bsolver.server.util.UserInfoCacheUtil;
import com.wjbgn.stater.dto.Result;
import com.wjbgn.stater.enums.CommonReturnEnum;
import com.wjbgn.stater.util.redis.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.Cardinality;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.collapse.CollapseBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Description:
 * Create Date: 2022-04-21T13:26:52.898
 *
 * @author wjbgn
 * @version 1.0
 */
@Service
public class BugAnsweredRecordServiceImpl implements IBugAnsweredRecordService {

    @Autowired
    private BugAnsweredRecordMapper bugAnsweredRecordMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserInfoCacheUtil userInfoCacheUtil;

    @Override
    public BugAnsweredRecordDO save(BugAnsweredRecordDO bugAnsweredRecordDO) {
        bugAnsweredRecordDO.setIsDelete(0);
        bugAnsweredRecordDO.setCreateTime(LocalDateTimeUtil.now());
        bugAnsweredRecordDO.setRejectNum(0L);
        bugAnsweredRecordDO.setAcceptNum(0L);
        return bugAnsweredRecordMapper.save(bugAnsweredRecordDO);
    }

    @Override
    public List<BugAnsweredRecordDTO> list(BugAnsweredRecordDO bugAnsweredRecordDO) {
        //分页查询
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("bugId", bugAnsweredRecordDO.getBugId()));
        //排序条件
        FieldSortBuilder sort = SortBuilders.fieldSort(SortEnum.CREATE_TIME.getField()).order(SortOrder.ASC);
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withSort(sort)
                .build();
        //分页查询
        Iterable<BugAnsweredRecordDO> search = bugAnsweredRecordMapper.search(build);
        List<BugAnsweredRecordDTO> bugAnsweredRecordDTOS = BugAnsweredRecordDoConvert.listConvert(Lists.newArrayList(search));
        bugAnsweredRecordDTOS.forEach(l -> {
            l.setCreateTimeStr(DateUtil.format(l.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            l.setCurrentHasAccept(false);
            l.setCurrentHasReject(false);
            l.setAcceptNum(redisUtil.bitCount("answered:accept:" + l.getId()));
            l.setRejectNum(redisUtil.bitCount("answered:reject:" + l.getId()));
            l.setNickname(userInfoCacheUtil.getUserNicknameByUsername(l.getUsername()));
            l.setBeAnsweredNickname(userInfoCacheUtil.getUserNicknameByUsername(l.getBeAnsweredUsername()));

        });
        if (StringUtils.isNotEmpty(bugAnsweredRecordDO.getUsername())) {
            Long userId = userInfoCacheUtil.getUserIdByUsername(bugAnsweredRecordDO.getUsername());
            bugAnsweredRecordDTOS.forEach(l -> {
                l.setCurrentHasAccept(redisUtil.getBitmap("answered:accept:" + l.getId(), userId));
                l.setCurrentHasReject(redisUtil.getBitmap("answered:reject:" + l.getId(), userId));
            });
        }
        return bugAnsweredRecordDTOS;
    }

    @Override
    public Page<BugAnsweredRecordDO> findByPageable(BugAnsweredRecordDTO bugAnsweredRecordDTO) {

        Page<BugAnsweredRecordDO> bugAnsweredRecordDOPage = new Page<>();
        SearchRequest searchRequest = new SearchRequest();
        try {
            //索引名称
            searchRequest.indices("bsolver_bug_answered_record");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            //根据ID进行排序
            sourceBuilder.sort(SortEnum.CREATE_TIME.getField());
            //分页
            sourceBuilder.from((bugAnsweredRecordDTO.getPage() - 1) * bugAnsweredRecordDTO.getLimit());
            sourceBuilder.size(bugAnsweredRecordDTO.getPage() * bugAnsweredRecordDTO.getLimit());
            BoolQueryBuilder query = new BoolQueryBuilder();
            sourceBuilder.query(query);
            CollapseBuilder collapseBuilder = new CollapseBuilder("bugId");
            sourceBuilder.collapse(collapseBuilder);
            sourceBuilder.aggregation(AggregationBuilders.cardinality("bugId").field("bugId"));
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            //各种查询
            queryBuilder.must(QueryBuilders.termQuery("username", bugAnsweredRecordDTO.getUsername()));
            //匹配策略
            query.must(queryBuilder);
            searchRequest.source(sourceBuilder);
            SearchResponse rp = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            List<BugAnsweredRecordDO> list = new ArrayList<>();
            for (SearchHit searchHit : rp.getHits()) {
                list.add(new BugAnsweredRecordDO(JSONObject.parseObject(searchHit.getSourceAsString()).getString("bugId")));
            }
            bugAnsweredRecordDOPage.setRecords(list);
            //去重总数
            Cardinality cardinality = rp.getAggregations().get("bugId");
            long value = cardinality.getValue();
            bugAnsweredRecordDOPage.setTotal(value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bugAnsweredRecordDOPage;
    }

    @Override
    public AchievementDTO getAcceptAndRejectNum(String username) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("bsolver_bug_answered_record");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        //各种查询
        builder.must(QueryBuilders.termQuery("username", username));
        //匹配策略
        sourceBuilder.query(builder);
        searchRequest.source(sourceBuilder);
        Long acceptNum = 0L;
        Long rejectNum = 0L;
        try {
            SearchResponse rp = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            for (SearchHit searchHit : rp.getHits()) {
                JSONObject jsonObject = JSONObject.parseObject(searchHit.getSourceAsString());
                acceptNum += jsonObject.getLong("acceptNum");
                rejectNum += jsonObject.getLong("rejectNum");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new AchievementDTO(acceptNum, rejectNum);
    }
}